unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, PythonEngine, PythonGUIInputOutput,
  Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Memo1: TMemo;
    PythonEngine1: TPythonEngine;
    PythonModule1: TPythonModule;
    PythonGUIInputOutput1: TPythonGUIInputOutput;
    btn1: TButton;
    btn2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure PythonModule1Initialization(Sender: TObject);
  private
    Ftmp: Tstringlist;
    OwnThreadState: PPyThreadState;
    function callback(pself, args: PPyObject): PPyObject; cdecl;
    { Private declarations }
  public
    { Public declarations }
  end;

  TSortThread = class(TPythonThread)
  private
    // FModule: TPythonModule;
    FScript: TStrings;
    fpyfuncname: string;
    running: Boolean;
  protected
    procedure ExecuteWithPython; override;
  public
    constructor create(script: TStrings);
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

uses varpyth, System.json;

var
  FModule: variant;
  ft1: TSortThread;

procedure TForm2.FormCreate(Sender: TObject);
begin
  Ftmp := Tstringlist.create;
end;

procedure TForm2.btn1Click(Sender: TObject);

var
  pyfunc: PPyObject;
begin
  with GetPythonEngine do
  begin
    OwnThreadState := PyThreadState_Get;
    PyEval_ReleaseThread(OwnThreadState);

    Ftmp.LoadFromFile('./server.py');
    ft1 := TSortThread.create(Ftmp);

    pyfunc := FindFunction(ExecModule, 'sendmsg');
    if Assigned(pyfunc) then
      try
        EvalFunction(pyfunc, [123]);
      except

      end;

    Py_DecRef(pyfunc);
  end;
end;

procedure TForm2.btn2Click(Sender: TObject);
var
  pyfunc: PPyObject;
begin
  with GetPythonEngine do
  begin
    Ftmp.LoadFromFile('./client.py');
    if Assigned(Ftmp) then
      ExecStrings(Ftmp);
    pyfunc := FindFunction(ExecModule, 'sendmsg');
    if Assigned(pyfunc) then
      try
        EvalFunction(pyfunc, ['123']);
      except

      end;

    Py_DecRef(pyfunc);
  end;
end;

function TForm2.callback(pself, args: PPyObject): PPyObject; cdecl;
begin
  with GetPythonEngine do
  begin
    ShowMessage('args of foo: ' + PyObjectAsString(args));
  end;
end;

procedure TForm2.PythonModule1Initialization(Sender: TObject);
begin
  //
  with Sender as TPythonModule do
  begin
    AddDelphiMethod('callback', callback, 'callback function');
  end;
end;

{ TSortThread }

constructor TSortThread.create(script: TStrings);
begin
  FScript := script;
  inherited create(false);
end;

procedure TSortThread.ExecuteWithPython;
var
  pyfunc: PPyObject;
begin
  running := true;
  with GetPythonEngine do
  begin
    if Assigned(FScript) then
      ExecStrings(FScript);
    pyfunc := FindFunction(ExecModule, 'startwb');
    if Assigned(pyfunc) then
      try
        EvalFunctionNoArgs(pyfunc);
      except

      end;

    Py_DecRef(pyfunc);
  end;
  running := false;
end;

end.
